using System;
using System.Collections.Generic;
using System.Text;

namespace CBM_Commander.DiskImageSharp
{
    public class D64 : ImageType
    {
        protected byte titleOffset = 144;
        protected string initMessage = "73,cbm dos 2.6 1541,00,00";
        protected byte interleave = 10;
        protected byte dirInterleave = 3;
        protected ushort tracks = 35;
        protected byte sides = 1;
        protected ushort headerTrack = 18;
        protected ushort bamTrack1 = 18;
        protected ushort bamTrack2 = 0;
        protected ushort bamSector1 = 0;
        protected ushort bamSector2 = 0;
        protected ushort defaultDirectoryTrack = 18;
        protected ushort defaultDirectorySector = 1;
        protected byte defaultDosVersion = 0x41;
        protected string defaultDosType = "2A";
        protected ushort[] trackSizes =
            new ushort[]
            {
                /* 01 */ 21,/* 02 */ 21,/* 03 */ 21,/* 04 */ 21,/* 05 */ 21,/* 06 */ 21,
                /* 07 */ 21,/* 08 */ 21,/* 09 */ 21,/* 10 */ 21,/* 11 */ 21,/* 12 */ 21,
                /* 13 */ 21,/* 14 */ 21,/* 15 */ 21,/* 16 */ 21,/* 17 */ 21,/* 18 */ 21,
                /* 19 */ 19,/* 20 */ 19,/* 21 */ 19,/* 22 */ 19,/* 23 */ 19,/* 24 */ 19,
                /* 25 */ 18,/* 26 */ 18,/* 27 */ 18,/* 28 */ 18,/* 29 */ 18,/* 30 */ 18,
                /* 31 */ 17,/* 32 */ 17,/* 33 */ 17,/* 34 */ 17,/* 35 */ 17
            };

        public D64() : base(d64) 
        {
            bamFields.BamRange = new byte[] { 0x04, 0x8f };
            bamFields.DiskDosVersionType = new byte[] { 0x02 };
            bamFields.DiskID = new byte[] { 0xA2, 0xA3 };
            bamFields.DiskName = new byte[] { 0x90, 0x9f };
            bamFields.DiskNamePadding = 0xA0;
            bamFields.DosType = new byte[] { 0xA5, 0xA6 };
            bamFields.DoubleSidedFlag = new byte[] { 0x03 };
            bamFields.DoubleSidedIndicator = 0x00;
            bamFields.SideTwoFreeSectors = null;
            
            FillRange unused1;
            unused1.Start = 0xA0;
            unused1.Stop = 0xA1;
            unused1.Value = 0xA0;

            FillRange unused2;
            unused2.Start = 0xA4;
            unused2.Stop = 0xA4;
            unused2.Value = 0xA0;

            FillRange unused3;
            unused3.Start = 0xA7;
            unused3.Stop = 0xAA;
            unused3.Value = 0xA0;

            FillRange unused4;
            unused4.Start = 0xAB;
            unused4.Stop = 0xFF;
            unused4.Value = 0x00;

            bamFields.fillRanges = new FillRange[]
            {
                unused1, unused2, unused3, unused4
            };
        }
    }

    public class D71 : ImageType
    {
        protected byte titleOffset = 144;
        protected string initMessage = "73,cbm dos v3.0 1571,00,00";
        protected byte interleave = 6;
        protected ushort tracks = 70;
        protected byte dirInterleave = 3;
        protected byte sides = 2;
        protected ushort headerTrack = 18;
        protected ushort bamTrack1 = 18;
        protected ushort bamTrack2 = 53;
        protected ushort bamSector1 = 18;
        protected ushort bamSector2 = 0;
        protected ushort defaultDirectoryTrack = 18;
        protected ushort defaultDirectorySector = 1;
        protected byte defaultDosVersion = 0x41;
        protected string defaultDosType = "2A";
        protected ushort[] trackSizes =
            new ushort[]
            {
                /* 01 */ 21,/* 02 */ 21,/* 03 */ 21,/* 04 */ 21,/* 05 */ 21,/* 06 */ 21,
                /* 07 */ 21,/* 08 */ 21,/* 09 */ 21,/* 10 */ 21,/* 11 */ 21,/* 12 */ 21,
                /* 13 */ 21,/* 14 */ 21,/* 15 */ 21,/* 16 */ 21,/* 17 */ 21,/* 18 */ 21,
                /* 19 */ 19,/* 20 */ 19,/* 21 */ 19,/* 22 */ 19,/* 23 */ 19,/* 24 */ 19,
                /* 25 */ 18,/* 26 */ 18,/* 27 */ 18,/* 28 */ 18,/* 29 */ 18,/* 30 */ 18,
                /* 31 */ 17,/* 32 */ 17,/* 33 */ 17,/* 34 */ 17,/* 35 */ 17,
                /* 36 */ 21,/* 37 */ 21,/* 38 */ 21,/* 39 */ 21,/* 40 */ 21,/* 41 */ 21,
                /* 42 */ 21,/* 43 */ 21,/* 44 */ 21,/* 45 */ 21,/* 46 */ 21,/* 47 */ 21,
                /* 48 */ 21,/* 49 */ 21,/* 50 */ 21,/* 51 */ 21,/* 52 */ 21,/* 53 */ 21,
                /* 54 */ 19,/* 55 */ 19,/* 56 */ 19,/* 57 */ 19,/* 58 */ 19,/* 59 */ 19,
                /* 60 */ 18,/* 61 */ 18,/* 62 */ 18,/* 63 */ 18,/* 64 */ 18,/* 65 */ 18,
                /* 66 */ 17,/* 67 */ 17,/* 68 */ 17,/* 69 */ 17,/* 70 */ 17
            };
        public D71() : base(d71) 
        {
            bamFields.BamRange = new byte[] { 0x04, 0x8f };
            bamFields.DiskDosVersionType = new byte[] { 0x02 };
            bamFields.DiskID = new byte[] { 0xA2, 0xA3 };
            bamFields.DiskName = new byte[] { 0x90, 0x9f };
            bamFields.DiskNamePadding = 0xA0;
            bamFields.DosType = new byte[] { 0xA5, 0xA6 };
            bamFields.DoubleSidedFlag = new byte[] { 0x03 };
            bamFields.DoubleSidedIndicator = 0x80;
            bamFields.SideTwoFreeSectors = new byte[] { 0xDD, 0xFF };

            FillRange unused1;
            unused1.Start = 0xA0;
            unused1.Stop = 0xA1;
            unused1.Value = 0xA0;

            FillRange unused2;
            unused2.Start = 0xA4;
            unused2.Stop = 0xA4;
            unused2.Value = 0xA0;

            FillRange unused3;
            unused3.Start = 0xA7;
            unused3.Stop = 0xAA;
            unused3.Value = 0xA0;

            FillRange unused4;
            unused4.Start = 0xAB;
            unused4.Stop = 0xDC;
            unused4.Value = 0x00;

            bamFields.fillRanges = new FillRange[]
            {
                unused1, unused2, unused3, unused4
            };
        }
    }

    public class D81 : ImageType
    {
        protected byte titleOffset = 4;
        protected string initMessage = "73,copyright cbm dos v10 1581,00,00";
        protected byte interleave = 1;
        protected byte dirInterleave = 1;
        protected ushort tracks = 80;
        protected byte sides = 2;
        protected ushort headerTrack = 40;
        protected ushort bamTrack1 = 40;
        protected ushort bamTrack2 = 40;
        protected ushort bamSector1 = 1;
        protected ushort bamSector2 = 2;
        protected ushort defaultDirectoryTrack = 40;
        protected ushort defaultDirectorySector = 3;
        protected byte defaultDosVersion = 0x44;
        protected string defaultDosType = "3D";
        protected ushort[] trackSizes =
            new ushort[]
            {
                /* 00 */ 40,/* 01 */ 40,/* 02 */ 40,/* 03 */ 40,/* 04 */ 40,
                /* 05 */ 40,/* 06 */ 40,/* 07 */ 40,/* 08 */ 40,/* 09 */ 40,
                /* 00 */ 40,/* 01 */ 40,/* 02 */ 40,/* 03 */ 40,/* 04 */ 40,
                /* 05 */ 40,/* 06 */ 40,/* 07 */ 40,/* 08 */ 40,/* 09 */ 40,
                /* 00 */ 40,/* 01 */ 40,/* 02 */ 40,/* 03 */ 40,/* 04 */ 40,
                /* 05 */ 40,/* 06 */ 40,/* 07 */ 40,/* 08 */ 40,/* 09 */ 40,
                /* 00 */ 40,/* 01 */ 40,/* 02 */ 40,/* 03 */ 40,/* 04 */ 40,
                /* 05 */ 40,/* 06 */ 40,/* 07 */ 40,/* 08 */ 40,/* 09 */ 40,
                /* 00 */ 40,/* 01 */ 40,/* 02 */ 40,/* 03 */ 40,/* 04 */ 40,
                /* 05 */ 40,/* 06 */ 40,/* 07 */ 40,/* 08 */ 40,/* 09 */ 40,
                /* 00 */ 40,/* 01 */ 40,/* 02 */ 40,/* 03 */ 40,/* 04 */ 40,
                /* 05 */ 40,/* 06 */ 40,/* 07 */ 40,/* 08 */ 40,/* 09 */ 40,
                /* 00 */ 40,/* 01 */ 40,/* 02 */ 40,/* 03 */ 40,/* 04 */ 40,
                /* 05 */ 40,/* 06 */ 40,/* 07 */ 40,/* 08 */ 40,/* 09 */ 40,
                /* 00 */ 40,/* 01 */ 40,/* 02 */ 40,/* 03 */ 40,/* 04 */ 40,
                /* 05 */ 40,/* 06 */ 40,/* 07 */ 40,/* 08 */ 40,/* 09 */ 40,
            };
        public D81()
            : base(d81)
        {
            bamFields.BamRange = new byte[] { 0x04, 0x8f };
            bamFields.DiskDosVersionType = new byte[] { 0x02 };
            bamFields.DiskID = new byte[] { 0x16, 0x17 };
            bamFields.DiskName = new byte[] { 0x04, 0x13 };
            bamFields.DiskNamePadding = 0xA0;
            bamFields.DosType = new byte[] { 0x19, 0x1a };
            bamFields.DoubleSidedFlag = new byte[] { 0x03 };
            bamFields.DoubleSidedIndicator = 0x00;
            bamFields.SideTwoFreeSectors = new byte[] { 0xDD, 0xFF };

            FillRange unused1;
            unused1.Start = 0x18;
            unused1.Stop = 0x18;
            unused1.Value = 0xA0;

            FillRange unused2;
            unused2.Start = 0x1B;
            unused2.Stop = 0x1C;
            unused2.Value = 0xA0;

            FillRange unused3;
            unused3.Start = 0x1D;
            unused3.Stop = 0xFF;
            unused3.Value = 0x00;

            bamFields.fillRanges = new FillRange[]
            {
                unused1, unused2, unused3
            };
        }
    }

    public abstract class ImageType 
    {
        protected readonly byte value;

        public static readonly byte d64 = 1;
        public static readonly byte d71 = 2;
        public static readonly byte d81 = 3;

        public ImageType(byte value)
        {
            this.value = value;
        }

        public override bool Equals(object obj)
        {
            if (!(obj is ImageType)) return false;
            ImageType target = (ImageType)obj;
            return value.Equals(target.value);
        }

        public override int GetHashCode()
        {
            return value.GetHashCode();
        }

        public override string ToString()
        {
            return value.ToString();
        }

        protected byte sides = 1;
        public byte Sides
        {
            get { return sides; }
        }

        protected ushort headerTrack = 0;
        public ushort HeaderTrack
        {
            get { return headerTrack; }
        }

        protected ushort bamTrack1 = 0;
        public ushort BamTrack1
        {
            get { return bamTrack1; }
        }

        protected ushort bamSector1 = 0;
        public ushort BamSector1
        {
            get { return bamSector1; }
        }

        protected ushort bamTrack2 = 0;
        public ushort BamTrack2
        {
            get { return bamTrack2; }
        }

        protected ushort bamSector2 = 0;
        public ushort BamSector2
        {
            get { return bamSector2; }
        }

        protected string initMessage = null;
        public string InitMessage
        {
            get { return initMessage; }
        }

        protected ushort tracks = 0;
        public ushort Tracks
        {
            get { return tracks; }
        }

        protected ushort[] trackSizes = new ushort[0];
        public ushort[] TrackSizes
        {
            get { return trackSizes; }
        }

        protected bool supportsDirectories = false;
        public bool SupportsDirectories
        {
            get { return supportsDirectories; }
        }

        public long ImageSize
        {
            get
            {
                return SectorCount * 256;
            }
        }

        public int SectorCount
        {
            get
            {
                int result = 0;

                for (int i = 1; i <= Tracks; i++)
                {
                    result += TrackSizes[i];
                }

                return result;
            }
        }

        protected byte titleOffset = 0;
        public byte TitleOffset
        {
            get { return titleOffset; }
        }

        protected BamFields bamFields;
        public BamFields BamFields
        {
            get { return bamFields; }
        }
    }
}
